#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <DNSServer.h>
#include "Ticker.h"

#ifndef STASSID
#define STASSID "Your Wi-Fi SSID"   //这设置Wi-Fi名字
#define STAPSK  "Your Wi-Fi Password" //这里设置Wi-Fi名字
#endif

#define PIN_CPU_DISPLAY 5 //
#define PIN_RAM_DISPLAY 12 //
#define PIN_DISPLAY_LED 14 //

enum LED_SHINE_SPEED {
  LED_SHINE_SLOW,
  LED_SHINE_MIDDLE,
  LED_SHINE_FAST,
};

int cpu_usage = 0;
int mem_usage = 0;
int cpu_usage_display = 0;
int mem_usage_display = 0;
Ticker displayTicker; //建立平滑处理定时器对象
Ticker ledTicker; //建立LED定时器对象

ESP8266WebServer server(80);
extern DNSServer dnsServer;
extern ESP8266WebServer server;
extern void wifiConfigInitBasic(void);
extern void wifiConfigConnectWifi(void);

const int led = LED_BUILTIN;

const String postForms = "<html>\
  <head>\
    <title>ESP8266 Web Server POST handling</title>\
    <style>\
      body { background-color: #cccccc; font-family: Arial, Helvetica, Sans-Serif; Color: #000088; }\
    </style>\
  </head>\
  <body>\
    <h1>update device data</h1><br>\
    <form method=\"post\" enctype=\"application/x-www-form-urlencoded\" action=\"/device/\">\
      <input type=\"text\" name=\"cpu_usage\" value=\"50\"><br>\
      <input type=\"text\" name=\"mem_usage\" value=\"60\"><br>\
      <input type=\"text\" name=\"led_onoff\" value=\"1\"><br>\
      <input type=\"submit\" value=\"Submit\">\
    </form>\
  </body>\
</html>";

void handleRoot() {
  digitalWrite(led, 1);
  server.send(200, "text/html", postForms);
  digitalWrite(led, 0);
}

void handleDevice() {
  if (server.method() != HTTP_POST) {
    digitalWrite(led, 1);
    server.send(405, "text/plain", "Method Not Allowed");
    digitalWrite(led, 0);
  } else {
    digitalWrite(led, 1);
    String message = "POST form was:\n";
    for (uint8_t i = 0; i < server.args(); i++) {
      message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
      if(server.argName(i) == "cpu_usage")
      {
        cpu_usage = server.arg(i).toInt();
        // analogWrite(15, cpu_usage*2.36);  // D8
        Serial.print("cpu usage:");
        Serial.println(cpu_usage);
      }
      else if(server.argName(i) == "mem_usage")
      {
        mem_usage = server.arg(i).toInt();
        // analogWrite(PIN_RAM_DISPLAY, mem_usage*10);  // D5
        Serial.print("mem usage:");
        Serial.println(mem_usage);
      }
      else if(server.argName(i) == "led_onoff")
      {
        int ledOnOff = server.arg(i).toInt();
        analogWrite(PIN_DISPLAY_LED, ledOnOff);
      }
    }
    server.send(200, "text/plain", message);
    Serial.println("=====================================================");
    digitalWrite(led, 0);
  }
}

void handleNotFound() {
  digitalWrite(led, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
  digitalWrite(led, 0);
}

void GPIO_init(void)
{
  pinMode(led, OUTPUT);
  digitalWrite(led, 0);
  analogWriteFreq(1000);
  analogWriteRange(1000);
  pinMode(PIN_CPU_DISPLAY, OUTPUT);
  analogWrite(PIN_CPU_DISPLAY, 0);
  pinMode(PIN_RAM_DISPLAY, OUTPUT);
  analogWrite(PIN_RAM_DISPLAY, 0);
  pinMode(PIN_DISPLAY_LED, OUTPUT);
  analogWrite(PIN_DISPLAY_LED, 0);
}

void WifiSmartConfig(void)
{
  WiFi.mode(WIFI_STA);
  Serial.println("\r\nWait for WifiSmartConfig...");
  WiFi.beginSmartConfig();
  while (1)
  {
    Serial.print(".");
    delay(500);                   // wait for a second
    if (WiFi.smartConfigDone())
    {
      Serial.println("WifiSmartConfig Success");
      Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
      Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
      break;
    }
  }
}

bool WifiAutoConnect()
{
  WiFi.hostname("PC Monitor");//设置ESP8266设备名
  WiFi.begin();
  int reconnc_timeout = 10; //重连超时时间，单位：秒
  for (int i = 0; i < reconnc_timeout; i++)
  {
    int wstatus = WiFi.status();
    if (wstatus == WL_CONNECTED)
    {
      Serial.println("Connect WIFI Success");
      Serial.printf("SSID:%s", WiFi.SSID().c_str());
      Serial.printf(", PSW:%s\r\n", WiFi.psk().c_str());
      Serial.print("LocalIP:");
      Serial.print(WiFi.localIP());
      Serial.print(" ,GateIP:");
      Serial.println(WiFi.gatewayIP());
      return true;
    }
    else
    {
      Serial.print("WIFI WifiAutoConnect Waiting......");
      Serial.println(wstatus);
      delay(1000);
    }
  }
  Serial.println("WIFI WifiAutoConnect Faild!" );
  return false;
}

void ConfigWifi(void)
{
  if (!WifiAutoConnect())
  {
  	WifiSmartConfig();
  }
}

void tickerHandle() //到时间时需要执行的任务
{
  if((cpu_usage*10+cpu_usage_display*9)/10 == cpu_usage_display && cpu_usage_display > (cpu_usage*10))
  {
    cpu_usage_display--;
  }
  else if((cpu_usage*10+cpu_usage_display*9)/10 == cpu_usage_display && cpu_usage_display < (cpu_usage*10))
  {
    cpu_usage_display++;
  }
  else
  {
    cpu_usage_display = (cpu_usage*10+cpu_usage_display*9)/10;
  }
  analogWrite(PIN_CPU_DISPLAY, cpu_usage_display*105/100);  // D8

  if((mem_usage*10+mem_usage_display*9)/10 == mem_usage_display && mem_usage_display > (mem_usage*10))
  {
    mem_usage_display--;
  }
  else if((mem_usage*10+mem_usage_display*9)/10 == mem_usage_display && mem_usage_display < (mem_usage*10))
  {
    mem_usage_display++;
  }
  else
  {
    mem_usage_display = (mem_usage*10+mem_usage_display*9)/10;
  }
  analogWrite(PIN_RAM_DISPLAY, mem_usage_display*105/100);
}

unsigned long ledCounter = 0;
unsigned long ledTickerHandler()
{
  return ledCounter++;
}

void TimerInit(void)
{
  displayTicker.attach(0.1,tickerHandle); //100ms
  ledTicker.attach(0.1, ledTickerHandler); //100ms
}

void ServerInit(void)
{
  server.on("/", handleRoot);
  server.on("/device/",handleDevice);
  server.onNotFound(handleNotFound);
  server.begin();
}

void IndicateInitDone(void)
{
  analogWrite(PIN_DISPLAY_LED, 500);
  delay(250);
  analogWrite(PIN_DISPLAY_LED, 0);
  delay(250);
  analogWrite(PIN_DISPLAY_LED, 500);
  delay(250);
  analogWrite(PIN_DISPLAY_LED, 0);
  delay(250);
}

void setup(void) {  
  GPIO_init();
  Serial.begin(115200);
  ConfigWifi();
  TimerInit();
  ServerInit();
  IndicateInitDone();
  Serial.println("HTTP server started");

}

void loop(void) {
  server.handleClient();
}